﻿#include "FITKRadiossDataPartAdaptor.h"
#include "FITK_Kernel/FITKCore/FITKEnumTransformer.hpp"
#include "FITK_Interface/FITKInterfaceIO/FITKAbstractHDF5Writer.h"
#include "FITK_Interface/FITKInterfaceIO/FITKAbstractHDF5Reader.h"
#include "FITK_Interface/FITKInterfaceIO/FITKHDF5FileTool.h"
#include "FITK_Interface/FITKInterfaceModel/FITKAbstractElement.h"
#include "FITK_Interface/FITKInterfaceModel/FITKElementFactory.h"
//RadiossData
#include "FITK_Component/FITKRadiossData/FITKRadiossNodesParts.h"

#include <QSet>

namespace Interface
{
    bool FITKRadiossDataPartAdaptor::adaptR()
    {
        _partData = dynamic_cast<Radioss::FITKRadiossPart*>(_dataObj);
        if (_reader == nullptr || _partData == nullptr || _h5Group == nullptr) return false;
        IO::FITKHDF5FileTool* h5tools = _reader->getHDF5FileTool();
        if (h5tools == nullptr) return false;
        int propId = -1;
        int matId = -1;
        int subsetId = -1;
        double thick = -1;
        if (!h5tools->readGroupint(*_h5Group, "PropId", &propId))return false;
        if (!h5tools->readGroupint(*_h5Group, "MatId", &matId))return false;
        if (!h5tools->readGroupint(*_h5Group, "SubSetId", &subsetId))return false;
        if (!h5tools->readGroupDouble(*_h5Group, "Thick", &thick))return false;
        // 设置零件属性
        _partData->setPropertyID(propId);
        _partData->setMaterialID(matId);
        _partData->setSubsetID(subsetId);
        _partData->setThickness(thick);

        if (!readRadiossData(_partData, *_h5Group)) return false;
        if (!readDataObject(_partData, *_h5Group)) return false;

        H5::Group eleGroup = _h5Group->openGroup("Ele");
        //获取行列
        int n, m;
        if (!getDataSetDim(eleGroup, "Element", n, m)) return false;
        hsize_t dimEleData[2]{ n ,m };
        //获取单元数据
        H5::DataSpace eleDataSpace(2, dimEleData);
        H5::DataSet eleDataSet = eleGroup.openDataSet("Element");
        //循环类型
        // 对同类单元进行每行循环读取数据
        for (int i = 0; i < n; ++i)
        {
            // hyperslab的开始
            hsize_t start[2] = { i, 0 };
            // hyperslab的步长
            hsize_t stride[2] = { 1, m };
            hsize_t count[2] = { 1, 1 };
            // Block sizes
            hsize_t block[2] = { 1, m };
            eleDataSpace.selectHyperslab(H5S_SELECT_SET, count, start, stride, block);
            hsize_t dim[] = { m * 2 };

            H5::DataSpace mspace2(1, dim);
            hsize_t start2[1] = { 0 };
            hsize_t stride2[1] = { 1 };
            hsize_t count2[1] = { m };
            hsize_t block2[1] = { 1 };
            mspace2.selectHyperslab(H5S_SELECT_SET, count2, start2, stride2, block2);

            int* ptIDArray = new int[m];
            eleDataSet.read(ptIDArray, H5::PredType::NATIVE_INT, mspace2, eleDataSpace);
            QList<int> nodes;
            int eleNodeCount = ptIDArray[2];
            if (eleNodeCount + 3 > m)return false;
            for (int k = 0; k < eleNodeCount; ++k)
            {
                nodes.append(ptIDArray[k + 3]);
            }
            Interface::FITKAbstractElement* element = Interface::FITKElementFactory::createElement(Interface::FITKModelEnum::FITKEleType(ptIDArray[1]));
            if (!element) return false;
            //添加点与单元
            element->setNodeID(nodes);
            element->setEleID(ptIDArray[0]);
            _partData->addElement(element);
  
            delete[] ptIDArray;
        }
        eleDataSet.close();
        return true;
    }

    bool FITKRadiossDataPartAdaptor::adaptW()
    {
        _partData = dynamic_cast<Radioss::FITKRadiossPart*>(_dataObj);
        if (_writer == nullptr || _partData == nullptr || _h5Group == nullptr) return false;
        IO::FITKHDF5FileTool* h5tools = _writer->getHDF5FileTool();
        if (h5tools == nullptr) return false;
        //写出零件数据
        int propId = _partData->getPropertyID();
        int matId = _partData->getMaterialID();
        int subsetId = _partData->getSubsetID();
        double thick = _partData->getThickness();
        h5tools->writeGroupAttrInt(*_h5Group, "PropId", propId);
        h5tools->writeGroupAttrInt(*_h5Group, "MatId", matId);
        h5tools->writeGroupAttrInt(*_h5Group, "SubSetId", subsetId);
        h5tools->writeGroupAttrDouble(*_h5Group, "Thick", thick);

        if (!writeRadiossData(_partData, *_h5Group))return false;
        if (!writeDataObject(_partData, *_h5Group))return false;

        H5::Group eleGroup = _h5Group->createGroup("Ele");
        int count = _partData->getElementCount();
        h5tools->writeGroupAttrInt(eleGroup, "ElementCount", count);

        int elemCount = _partData->getElementCount();
        int maxLength = 0;
        for (int i = 0; i < elemCount; ++i)
        {
            //单元
            auto ele = _partData->getElementAt(i);
            if (!ele)continue;
            int num = ele->getNodeCount();
            if (maxLength < num)
                maxLength = num;
        }
        int lineSize = maxLength + 3;
        hsize_t dimEleData[2]{ elemCount ,lineSize };

        H5::DataSpace eleDataSpace(2, dimEleData);
        H5::DataSet eleDataSet = eleGroup.createDataSet("Element", H5::PredType::NATIVE_INT, eleDataSpace);
        // 对同类单元进行循环
        for (int i = 0; i < elemCount; ++i)
        {
            // hyperslab的开始
            hsize_t start[2] = { i, 0 };
            // hyperslab的步长
            hsize_t stride[2] = { 1, lineSize };
            hsize_t count[2] = { 1, 1 };
            // Block sizes
            hsize_t block[2] = { 1, lineSize };
            eleDataSpace.selectHyperslab(H5S_SELECT_SET, count, start, stride, block);
            hsize_t dim[] = { lineSize * 2 };

            H5::DataSpace mspace2(1, dim);
            hsize_t start2[1] = { 0 };
            hsize_t stride2[1] = { 1 };
            hsize_t count2[1] = { lineSize };
            hsize_t block2[1] = { 1 };
            mspace2.selectHyperslab(H5S_SELECT_SET, count2, start2, stride2, block2);
            //写入单元数据
            auto ele = _partData->getElementAt(i);
            if (!ele)continue;
            int eleNodeCount = ele->getNodeCount();
            int* ptIDArray = new int[lineSize];
            for (int k = 0; k < eleNodeCount; ++k)
                ptIDArray[k + 3] = ele->getNodeID(k);
            ptIDArray[0] = ele->getEleID();
            ptIDArray[1] = ele->getEleType();
            ptIDArray[2] = eleNodeCount;
            eleDataSet.write(ptIDArray, H5::PredType::NATIVE_INT, mspace2, eleDataSpace);
            delete[] ptIDArray;
        }
        eleDataSet.close();

        return true;
    }
    bool FITKRadiossDataPartAdaptor::getDataSetDim(H5::Group& h5group, std::string name, int& n, int& m)
    {
        if (!h5group.nameExists(name)) return false;
        H5::DataSet dataSet = h5group.openDataSet(name);
        H5::DataSpace space = dataSet.getSpace();
        hsize_t       dim[2];
        space.getSimpleExtentDims(dim);
        n = dim[0];
        m = dim[1];
        return true;
    }
}
